home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / prolog / sbprolog / amiga / c_src2_5.zoo / loader.c < prev    next >
C/C++ Source or Header  |  1990-06-03  |  19KB  |  640 lines

  1. /************************************************************************
  2. *                                    *
  3. * The SB-Prolog System                            *
  4. * Copyright SUNY at Stony Brook, 1986; University of Arizona, 1987    *
  5. *                                    *
  6. ************************************************************************/
  7.  
  8. /*-----------------------------------------------------------------
  9. SB-Prolog is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY.  No author or distributor
  11. accepts responsibility to anyone for the consequences of using it
  12. or for whether it serves any particular purpose or works at all,
  13. unless he says so in writing.  Refer to the SB-Prolog General Public
  14. License for full details.
  15.  
  16. Everyone is granted permission to copy, modify and redistribute
  17. SB-Prolog, but only under the conditions described in the
  18. SB-Prolog General Public License.   A copy of this license is
  19. supposed to have been given to you along with SB-Prolog so you
  20. can know your rights and responsibilities.  It should be in a
  21. file named COPYING.  Among other things, the copyright notice
  22. and this notice must be preserved on all copies. 
  23. ------------------------------------------------------------------ */
  24.  
  25. /* loader.c */
  26.  
  27. /* modification history  ----------
  28.      07/16/89 - index.h now included
  29.            added SEPARATOR definition 
  30. ************************/           
  31.  
  32. #include "sim.h"
  33. #ifdef AMIGA
  34. #include "index.h"
  35. #endif
  36. #include "inst.h"
  37. #include "aux.h"
  38.  
  39.  
  40. #define get_data(x,y)     (y - fread(x, sizeof(*x), y, fp) )
  41. #define st_ptrptrpsc(i_addr)  *((pw *)i_addr) = reloc_table[*(pw)i_addr];
  42. #define st_ptrpsc(i_addr)  *((pw)i_addr) = *reloc_table[*(pw)i_addr];
  43.  
  44. #ifdef AMIGA
  45. #define SEPARATOR '!' /* character to separate search paths */
  46. #else 
  47. #define SEPARATOR ':' /* SIMPATH = '.../modlib:.../cmplib:...*/
  48. #endif
  49.  
  50. static pb inst_addr, hptr;
  51.  
  52. static pw reloc_table[500];
  53. static byte *last_text;
  54.  
  55. unsigned long eof_flag;
  56. unsigned long psc_bytes, text_bytes, index_bytes, magic;
  57. int (*load_routine[16])();
  58. static   FILE *fp;
  59. static byte perm = PERM;
  60. int inst_length[15] = { 0, 4, 6, 6, 2, 6, 6, 6, 6, 10, 6, 6, 2, 4, 10};
  61.  
  62.  
  63. /****************************************************************************/
  64. /*                                        */
  65. /* fix_bb: fixes the byte-backwards problem. It is passed a pointer to a    */
  66. /* sequence of 4 bytes read in from a file as bytes. It then converts those */
  67. /* bytes to represent a number. This code works for any machine, and makes  */
  68. /* the byte-code machine independent.                                       */
  69. /*                                        */
  70. /****************************************************************************/
  71.  
  72. void fix_bb(lptr)
  73. unsigned char *lptr;
  74. {
  75.     unsigned long *numptr;
  76.  
  77.     numptr = (unsigned long *)lptr;
  78.     *numptr = (((((*lptr << 8) | *(lptr+1)) 
  79.             << 8) | *(lptr+2)) 
  80.             << 8) | *(lptr+3);
  81.  
  82. }
  83.  
  84.  
  85. /****************************************************************************/
  86. /*                                        */
  87. /*    Load the file into permanent space, starting from "curr_fence".       */
  88. /* Data segment first (mixed psc entries and name strings), then text       */
  89. /* segment, ended with a virtual instruction "endfile <pointer>" where the  */
  90. /* pointer is a pointer to the next text segment (of another byte code      */
  91. /* file).                                    */
  92. /*                                        */
  93. /****************************************************************************/
  94.  
  95. int loader(file)
  96. char *file;
  97.   byte *restore;
  98.   int err_msg;
  99.  
  100.   fp = fopen(file, "r");
  101.   if ( fp == NULL ) return 10;
  102.   printf("\n     ...... loading file %s\n", file);
  103.  
  104.  
  105.   while ((eof_flag = get_data(&magic, 1)) == 0) { 
  106.     if (eof_flag = get_data(&psc_bytes, 1)) return ( 1 );
  107.     if (eof_flag = get_data(&text_bytes, 1)) return ( 1 );
  108.     if (eof_flag = get_data(&index_bytes, 1)) return ( 1 );
  109.     err_msg = load_syms() ;
  110.     if ( err_msg != 0 ) {
  111.     printf("error %d loading file %s\n", err_msg, file);
  112.     exit(1);   /* eventually upper level routines will determine */
  113.     }
  114.     else {
  115.     restore =  curr_fence;
  116.     err_msg = load_text(); 
  117.     if (err_msg != 0) {
  118.         printf("error %d loading file %s\n", err_msg, file);
  119.         curr_fence =  restore;
  120.         exit(1);  /* eventually upper level routines will determine */
  121.     } else {
  122.         err_msg = load_index();
  123.         if (err_msg != 0) {
  124.         printf("error in loading file %s\n", err_msg, file);
  125.         curr_fence = restore;
  126.         exit(1); /*eventually upper level routines will determine */
  127.         } else {
  128.         if (eof_flag = get_data(inst_addr, 6)) return (eof_flag);
  129.         if (*inst_addr != endfile)    *inst_addr = endfile;
  130.         inst_addr += 6;
  131.         *((pw)(inst_addr-4)) = 0;
  132.         last_text = inst_addr - 4;
  133.         curr_fence = inst_addr;
  134.         if (curr_fence > max_fence) quit("Program area overflow\n");
  135.         }
  136.     }
  137.     }
  138.   }
  139.   fclose(fp);
  140.   return 0;
  141. }
  142.  
  143.  
  144. /************************************************************************
  145. *                                                                       *
  146. * Load_syms is a function which loads a symbol table given in a byte    *
  147. * code file into an appropriate format in the pcs table.  As part of    *
  148. * its function it resolves entry points for byte code intructions (call *
  149. * to relloc_addr), and maintains a tableau so that instructions         *
  150. * with indexes into the psc table may have those indexex resloved before*
  151. * loading them in the intruction array (byte code program space).  The  *
  152. * intructions are loaded by a separate function.                        *
  153. * The function returns a short integer which is a error code.  Relevant *
  154. * error codes are listed below.                                         *
  155. *                                                                       *
  156. *      1: in load_syms: incomplete or missing psc count                 *
  157. *      2: in load_syms: incomplete or missing ep in record dec          *
  158. *      3: in load_syms: incomplete or missing arity in record dec       *
  159. *      4: in load_syms: incomplete or missing length in record dec      *
  160. *      5: in load_syms: incomplete or missing name in record dec        *
  161. *      8: can not open file                                             *
  162. *                                                                       *
  163. ************************************************************************/
  164.  
  165. int load_syms()
  166. {
  167.    char          name[256];
  168.    int               ep_offset;
  169.    byte     *reloc_addr( );
  170.    unsigned long     i, j, count;
  171.    byte     temp_len;
  172.    byte     temp_arity;
  173.    word *insert ( );
  174.  
  175.    i = 0; count = 0;
  176.    fix_bb(&psc_bytes); /* caller read psc_bytes, we just fix it */
  177.    while ( (count < psc_bytes) && (eof_flag == 0) ) {
  178.       if ( eof_flag = get_data(&ep_offset, 1) ) return(2);
  179.       fix_bb(&ep_offset);
  180.       if ( eof_flag = get_data(&temp_arity,1) ) return(3);
  181.       if ( eof_flag = get_data(&temp_len,1) ) return(4);
  182.       if ( eof_flag = get_data(name, temp_len) ) return(5);
  183.       reloc_table[i] = insert(name, temp_len, temp_arity, &perm);
  184.  
  185.       set_temp_ep(*reloc_table[i], ep_offset);
  186.       count += temp_len + 6; i++;
  187.    }
  188.    for (j = 0; j < i; j++) {
  189.       set_real_ep(*reloc_table[j], curr_fence);
  190.    }
  191.    pspace_used = ((int)curr_fence - (int)(pspace))/4;
  192.    return(0);
  193. }  /* load_syms */
  194.  
  195.  
  196.  
  197. /************************************************************************
  198. *                                                                       *
  199. *  Load_text loads the byte code intruction from a byte code file to    *
  200. *  the byte code program space.  References to indexes to the pcs table *
  201. *  are resolved with the use of the macro st_index.  New index  relies  *
  202. *  on the symbol table array which is assigned values by load_syms.     *
  203. *  The routine assumes the current length 8/18/84 of byte code          *
  204. *  intructions when reading from the byte code file.                    *
  205. * The function returns a short integer which is a error code.  Relevant *
  206. * error codes are listed below.                                         *
  207. *                                                                       *
  208. *      6: in load_text: byte code Operands are non-existent             *
  209. *      7: in load_text: Illegal instruction from PIL file               *
  210. *      8: can not open file                                             *
  211. *                                                                       *
  212. ************************************************************************/
  213.  
  214. int load_text ()
  215. {
  216.    long current_opcode = 0;
  217.    long count = 0;   
  218.    byte *reloc_addr( );
  219.  
  220. /* set text segments chain */
  221.    if (inst_begin == 0) { 
  222.         inst_begin = curr_fence;
  223.    } else *((word *)last_text) = (word)curr_fence;
  224.  
  225.    inst_addr = curr_fence;
  226.    fix_bb(&text_bytes);
  227.    while ( (count < text_bytes) &&
  228.        ((eof_flag = get_data(inst_addr, 1)) == 0) ) {
  229.        current_opcode = *(inst_addr++);
  230.        (*load_routine[parse_table[current_opcode]])();
  231.        count += inst_length[parse_table[current_opcode]];
  232.    }
  233.    if (count != text_bytes) return ( 9 ); /* missing instructions */
  234.    return(0);
  235.  
  236. }  /* load_text */
  237.  
  238. int load_index()
  239. {
  240.   long  psc_offset, clause_no, temp_len;
  241.   long  count = 0;
  242.   pw psc;
  243.   pb gen_index();
  244.  
  245.   fix_bb(&index_bytes);
  246.   while ( (count < index_bytes) && (eof_flag == 0) ) {
  247.       if (eof_flag = get_data(&psc_offset, 1)) return (10); 
  248.       fix_bb(&psc_offset);
  249.       psc = (pw)(*reloc_table[psc_offset]);
  250.       if (eof_flag = get_data(&clause_no, 1)) return (1);
  251.       fix_bb(&clause_no);
  252.       if (eof_flag = get_index_tab(clause_no, &temp_len)) return (eof_flag);
  253.       inst_addr = gen_index(clause_no, psc);
  254.       count += 8 + temp_len;
  255.   }
  256.   return (0);
  257. }
  258.  
  259. int get_index_tab(clause_no, lenptr)
  260.   long clause_no, *lenptr;
  261. {
  262.   long hashval, size, j;
  263.   long count = 0;
  264.   byte  type;
  265.   word val;
  266.   pb label, reloc_addr();
  267.  
  268.   hptr = (pb)hreg;
  269.   size = hsize(clause_no);
  270.   for (j = 0; j < size; j++) {
  271.       indextab[j].l = 0;
  272.       indextab[j].link = (pw)&(indextab[j].link);
  273.   }
  274.   for (j = 0; j< clause_no; j++) {
  275.       if (eof_flag = get_data(&type, 1)) return (11);
  276.          switch (type) {
  277.         case 'i': if (eof_flag = get_data(&val, 1)) return (12);
  278.               fix_bb(&val); count += 9;
  279.               break;
  280.         case 'l': val = *((pw)untagged(list_str)); 
  281.               /* val = untagged(list_str); */
  282.               count += 5;
  283.               break;
  284.             case 'n': /* val = untagged(nil_sym); */
  285.               val = *((pw)untagged(nil_sym));
  286.               count += 5;
  287.               break;
  288.         case 's': if (eof_flag = get_data(&val, 1)) return (12);
  289.               fix_bb(&val); count += 9;
  290.               val = *reloc_table[val];
  291.               /* val = (word)reloc_table[val]; */
  292.               break;
  293.         case 'c': if (eof_flag = get_data(&val, 1)) return (12);
  294.               fix_bb(&val); count += 9;
  295.               val = *reloc_table[val];
  296.               /* val = (word)reloc_table[val]; */
  297.               break; 
  298.      }
  299.          if (eof_flag = get_data(&label, 1)) return (13);
  300.      fix_bb(&label);
  301.          label = reloc_addr((long)label);
  302.          hashval = ihash(val, size);
  303.          inserth(label, &indextab[hashval]);
  304.   }
  305.   *lenptr = count;
  306.   return (0);
  307. }
  308.  
  309. byte *gen_index(clause_no, psc)
  310.   long clause_no;
  311.   struct psc_rec *psc;
  312. {
  313.   pb  ep1, ep2;
  314.   long j, size;
  315.   pw temp;
  316.  
  317.   size = hsize(clause_no);
  318.   ep1 = inst_addr;
  319.   *(ep1++) = hash; *(ep1++) = size;
  320.   ep2 = (inst_addr + 2 + 4 * size);
  321.   temp = (pw)(psc->ep + 2);         /* here the hash table size is */
  322.   *(temp++) = (long)inst_addr + 2;    /* computed and inserted into  */
  323.   *(temp) = size;            /* sob instructions           */
  324.   for (j = 0; j < size; j++) {
  325.       if (indextab[j].l == 0) {
  326.        *((pb *)ep1) = trap_vector[0]; ep1 += 4;
  327.       } else  if (indextab[j].l == 1) {
  328.        *((pw)ep1) = *(indextab[j].link); ep1 += 4;
  329.       } else {
  330.       /* otherwise create try/retry/trust instruction */
  331.       *((pb *)ep1) = ep2; ep1 += 4;
  332.       temp = (indextab[j].link);
  333.       gentry(try, psc->arity, *temp++, ep2);
  334.       while (*temp != (word)temp) {
  335.          temp = (pw)(*temp);
  336.          gentry(retry, psc->arity, *temp++, ep2);
  337.       }
  338.       *(ep2 - 6) = trust;
  339.       }
  340.   }
  341.   return (ep2);
  342.  
  343. }
  344.  
  345. inserth(label, bucket)
  346.   byte *label;
  347.   struct hrec *bucket;
  348.   pw temp;
  349.  
  350.   bucket->l++;
  351.   temp = (pw)&(bucket->link);
  352.   if (bucket->l > 1) {
  353.        temp = (pw)*temp;
  354.        while ((pw)*temp != temp) 
  355.           temp = (pw)*(++temp);
  356.   }
  357.   *temp = (word)hptr;
  358.   *((pb *)hptr) = label; hptr +=4;
  359.   *((pb *)hptr) = hptr; hptr += 4;
  360. }
  361.  
  362. int hsize(numentry)
  363.    long numentry;
  364. {  int i, j, temp;
  365.  
  366.    temp = numentry + 1;
  367.    hashsod:
  368.       j = temp / 2 + 1;
  369.       for (i = 2; i <= j; i++) {
  370.     if ((i != temp) && ((temp % i) == 0)) { temp++; goto hashsod;}
  371.       }
  372.       return ( temp );
  373. }
  374.  
  375. /************************************************************************
  376. *                                                                       *
  377. * Reloc_addr calculates the entry point of the code using the entry     *
  378. * point stored in the byte code file as an offset, and the stack        *
  379. * pointer curr_fence as the relative address.  Note trap vectors are    *
  380. * are indicated with a - 1, in the byte code file.                      *
  381. *                                                                       *
  382. ************************************************************************/
  383.  
  384.  
  385. byte *reloc_addr(offset)
  386.  
  387. long offset;
  388.  
  389. {
  390.    if ( offset >= 0 ) {
  391.       return curr_fence + offset;
  392.    }
  393.    else {
  394.       if ( -(offset+1) <= maxtraps ) {
  395.          return trap_vector[-(offset+1)];
  396.       }
  397.       else
  398.          return curr_fence + offset;   /* ??? */
  399.    }
  400. }  /* reloc_addr */
  401.  
  402.  
  403.  
  404.  
  405. int l_E()
  406. {
  407. }
  408.  
  409. int l_B()
  410. {
  411.              if ( get_data(inst_addr,1) ) 
  412.                 quit("incomplete instruction\n");
  413.              else inst_addr++;
  414. }
  415.  
  416. int l_PBB()
  417. {
  418.     /* operand 1 = 1 byte; operand 2 = 1 byte */
  419.              if ( get_data(inst_addr, 3) )
  420.              quit("incomplete instruction\n");
  421.              else  inst_addr += 3;
  422. }
  423.  
  424. int l_PW()
  425. {
  426.     /* operand 1 = 4 bytes index */
  427.              if ( get_data(inst_addr,5) ) 
  428.         quit("incomplete instruction\n"); 
  429.              else {
  430.         inst_addr++;
  431.         fix_bb(inst_addr);
  432.                 st_ptrpsc(inst_addr);
  433.                 inst_addr += 4;
  434.              }
  435. }
  436.  
  437. int l_PC()
  438. {
  439.     /* operand 1 = 4 bytes index */
  440.              if ( get_data(inst_addr,5) ) 
  441.         quit("incomplete instruction\n"); 
  442.              else {
  443.         inst_addr++;
  444.         fix_bb(inst_addr);
  445.                 st_ptrptrpsc(inst_addr);
  446.                 inst_addr += 4;
  447.              }
  448. }
  449.  
  450. int l_BW()
  451. {
  452.     /* operand 1 = 4 bytes index; operand 2 = 1 byte */
  453.              if ( get_data(inst_addr,5) ) 
  454.         quit("incomplete instruction\n"); 
  455.              else {
  456.            inst_addr++;
  457.                fix_bb(inst_addr);
  458.            st_ptrpsc(inst_addr);
  459.                inst_addr += 4;
  460.               }
  461. }
  462.  
  463. int l_BC()
  464. {
  465.     /* operand 1 = 4 bytes index; operand 2 = 1 byte */
  466.              if ( get_data(inst_addr,5) ) 
  467.         quit("incomplete instruction\n"); 
  468.              else {
  469.            inst_addr++;
  470.                fix_bb(inst_addr);
  471.            st_ptrptrpsc(inst_addr);
  472.                inst_addr += 4;
  473.               }
  474. }
  475.  
  476. int l_PA()
  477. {
  478.     /* operand 1 = 4 bytes address */
  479.              if ( get_data(inst_addr, 5) ) 
  480.         quit("incomplete instruction\n"); 
  481.              else {
  482.         inst_addr++;
  483.                 fix_bb(inst_addr);
  484.         *(pb *)inst_addr = reloc_addr(*(pw)inst_addr);
  485.                 inst_addr += 4;
  486.              }
  487. }
  488.  
  489. int l_PL()
  490. {
  491.     /* operand 1 = 4 bytes number */
  492.              if ( get_data(inst_addr, 5) ) 
  493.         quit("incomplete instruction\n"); 
  494.              else {
  495.              inst_addr++;
  496.          fix_bb(inst_addr);
  497.          inst_addr += 4;
  498.          }
  499. }
  500.  
  501. int l_BL()
  502. {
  503.     /* operand 1 = 4 bytes number; operand 2 = 1 byte reg */
  504.              if ( get_data(inst_addr, 5) ) 
  505.         quit("incomplete instruction\n");
  506.              else {
  507.              inst_addr++;
  508.          fix_bb(inst_addr);
  509.          inst_addr += 4;
  510.          }
  511. }
  512.  
  513.  
  514. int l_BA()
  515. {
  516.      /* operand 1 = 1 byte reg; operand 2 = 4 bytes address */
  517.              if ( get_data(inst_addr, 1) ) 
  518.         quit("incomplete instruction\n"); 
  519.              else {
  520.                 inst_addr++;
  521.                 if ( get_data(inst_addr, 4) ) 
  522.                     quit("incomplete instruction\n"); 
  523.                 else {
  524.            fix_bb(inst_addr);
  525.                    *(pb *)inst_addr = reloc_addr(*(pw)inst_addr);
  526.                    inst_addr += 4;
  527.                 }
  528.              }
  529. }
  530.  
  531.  l_BAA()
  532. {
  533.     /* oprnd1= 1 byte reg; oprnd1, oprnd2= 4 bytes addr */ 
  534.              if ( get_data(inst_addr, 1) ) 
  535.                  quit("incomplete instruction\n"); 
  536.              else {
  537.                  inst_addr++;
  538.                  if ( get_data(inst_addr, 4) ) 
  539.                      quit("incomplete instruction\n"); 
  540.                  else {
  541.             fix_bb(inst_addr);
  542.                     *(pb *)inst_addr = reloc_addr(*(pw)inst_addr);
  543.                     inst_addr += 4;
  544.                     if ( get_data(inst_addr, 4) ) 
  545.                         quit("incomplete instruction\n"); 
  546.                     else {
  547.                fix_bb(inst_addr);
  548.                        *(pb *)inst_addr = reloc_addr(*(pw)inst_addr);
  549.                        inst_addr += 4;
  550.             }
  551.                  }
  552.              }
  553. }
  554.  
  555. int l_P()
  556. {
  557.     /* only a pad byte, no operand */
  558.              if ( get_data(inst_addr, 1) ) 
  559.         quit("incomplete instruction\n"); 
  560.              else inst_addr++;
  561. }
  562.  
  563. int l_BBB()
  564. {
  565.     /* operand 1 = 1 byte; operand 2 = 1 byte; operand 3 = 1 byte */
  566.              if ( get_data(inst_addr, 3) )
  567.              quit("incomplete instruction\n");
  568.              else  inst_addr += 3;
  569. }
  570.  
  571. void init_load_routine()
  572. {
  573.     load_routine[E] = l_E;
  574.     load_routine[PBB] = l_PBB;
  575.     load_routine[BW] = l_BW;
  576.     load_routine[BC] = l_BC;
  577.     load_routine[B] = l_B;
  578.     load_routine[PW] = l_PW;
  579.     load_routine[PC] = l_PC;
  580.     load_routine[PL] = l_PL;
  581.     load_routine[BA] = l_BA;
  582.     load_routine[BAA] = l_BAA;
  583.     load_routine[PA] = l_PA;
  584.     load_routine[BL] = l_BL;
  585.     load_routine[P] = l_P;
  586.     load_routine[BBB] = l_BBB;
  587. }
  588.  
  589. int dyn_loader(psc_ptr)
  590. struct psc_rec *psc_ptr;
  591. {
  592.   extern char *getenv();
  593.   char s[256], s1[36], *s2, s3[256];
  594.   int i;
  595.  
  596.      namestring(psc_ptr, s1); printf("namestring returns %s\n",s1);
  597. if(loader(s1)==0) return(0);
  598. #ifdef AMIGA
  599.     /* if absolute path name then try to load
  600.     I define absolute path names for the Amiga
  601.     as    -has a device name(': present)
  602.         -does not start with parent '/'
  603.         -does not start with current directory '.'
  604.          */
  605.     if(index(s1,'!') && (*s1 != '.' && *s1 != '/'))
  606.     {printf("loading only %s\n",s1); return(loader(s1));}
  607. #endif
  608.      if (*s1 == '/') return loader(s1);
  609.      else 
  610.  
  611. #ifdef AMIGA /* chop off ./ for Amiga */
  612.      if(*s1 == '.' && strlen(s1) >2) return loader(&s1[2]);
  613. #else
  614.     if (*s1 == '.') return loader(s1);
  615. #endif
  616.  
  617.      else {
  618.     printf("using dynamic loader! %s\n", s1);
  619.     s2 = getenv("SIMPATH");
  620.  
  621.     while (1) {
  622.         while (*s2 == SEPARATOR || *s2 == ' ') s2++;
  623.         i = 0;
  624.         if (*s2 == '\0') {
  625. printf("file not found\n");
  626.          /* file not found */
  627.         return 1;
  628.         }
  629.         while (*s2 && *s2 != ' ' && *s2 != SEPARATOR) s[i++] = *(s2++);
  630.         printf("s is %s ",s);
  631.         s[i++] = '/';
  632.         s[i] = '\0';
  633.         scat(s, s1, s3);printf("trying to load %s\n",s3);
  634.         if (loader(s3) == 0) return 0;       
  635.     }
  636.     }
  637. }
  638.